-----------------------------------------------------------------------
-- File:        Dio192_Blocks.adb
-- Description: Provides an interface to the low level hardware control
--		    of blocks, it sets the Cab and polarity of a block,
--              it init blocks and flips the polarity of a block.
--
-- Requires:    Io_Ports,Unsigned_Types,Raildefs,Dio192defs, Dda06defs,
--              Int32defs
--
--				
-- Author:     Maria Mitrevska
-----------------------------------------------------------------------
with Io_Ports;
with Unsigned_Types;
use Unsigned_Types;  -- 1.8
with Raildefs,
   Dio192defs, Dda06defs, Int32defs, Halls2;
use Raildefs;


package body Dio192_Blocks is --PROTECTED

   --Declaration of types
   type Block_Reg_Array is array (Raildefs.Block_Idx range 0 .. 11) of Dio192defs.Block_Register;

   --Protected Object Declaration
   protected Object is

      --Set block Cab
      procedure Set_Cab (
            B   : in     Raildefs.Block_Id;
            Cab : in     Raildefs.Cab_Type);

      --Set block polarity
      procedure Set_Polarity (
            B   : in     Raildefs.Block_Id;
            Pol : in     Raildefs.Polarity_Type);

      --Flip block polarity
      procedure Flip_Block (
            B : in     Raildefs.Block_Id);

      --Init blocks
      procedure Init_Blocks;

   private
      --Protected Members
      Block_Regs : Block_Reg_Array:= (others => Dio192defs.Zero_Normal);

   end Object;


   --Protected Object Body
   protected body Object is

      --Set block Cab
      procedure Set_Cab (
            B   : in     Raildefs.Block_Id;
            Cab : in     Raildefs.Cab_Type) is
         use         Raildefs,
         Dio192defs;
         Index      : Raildefs.Block_Idx := (B - 1) / 2; -- 0..11
         Nibble     : Raildefs.Block_Idx := B
         mod 2; -- note asymmetry for big-end first
      begin

         Block_Regs(Index)(Nibble).Blk_Cab := Cab; --power the CAB
         Io_Ports.Write_Io_Port( Block_Addr(Index),Unsigned(Block_Regs(
                  Index)) );

      end Set_Cab;

      --Set block polarity
      procedure Set_Polarity (
            B   : in     Raildefs.Block_Id;
            Pol : in     Raildefs.Polarity_Type) is
         use         Raildefs,
         Dio192defs;
         Index      : Raildefs.Block_Idx := (B - 1) / 2; -- 0..11
         Nibble     : Raildefs.Block_Idx := B
         mod 2; -- note asymmetry for big-end first

      begin

         Block_Regs(Index)(Nibble).Blk_Pol := Pol; --set the polarity
         Io_Ports.Write_Io_Port( Block_Addr(Index),Unsigned(Block_Regs(
                  Index)) );

      end Set_Polarity;


      --Flip block polarity
      procedure Flip_Block (
            B : in     Raildefs.Block_Id) is
         use         Raildefs,
         Dio192defs;
         Temp       : Raildefs.Polarity_Type;
         Index      : Raildefs.Block_Idx     := (B - 1) / 2; -- 0..11
         Nibble     : Raildefs.Block_Idx     := B
         mod 2;
      begin
         Temp :=  Block_Regs(Index)(Nibble).Blk_Pol;
         Block_Regs(Index)(Nibble).Blk_Pol := Raildefs.Opposite(Temp);
         Io_Ports.Write_Io_Port( Block_Addr(Index),Unsigned(Block_Regs(
                  Index)) );
      end Flip_Block;

      --Init Blocks
      procedure Init_Blocks is
         use Dio192defs;
         Temp : Unsigned_8;
      begin

         -- init 24-bits output 4 times
         Io_Ports.Write_Io_Port(Pctl1_Addr, Output_Init1);
         Io_Ports.Write_Io_Port(Qctl1_Addr, Output_Init1);
         Io_Ports.Write_Io_Port(Pctl2_Addr, Output_Init1);
         Io_Ports.Write_Io_Port(Qctl2_Addr, Output_Init1);
         -- init 24-bits mixed input & output
         Io_Ports.Write_Io_Port(Pctl3_Addr, Pctl3_Init1);
         Io_Ports.Write_Io_Port(Qctl3_Addr, Qctl3_Init1);


         for I in Block_Regs'range loop
            Block_Regs(I) := Zero_Normal;
            Io_Ports.Write_Io_Port(Block_Addr(I), Unsigned(Block_Regs(I)));
         end loop;

         -- finish initialisation, tristate on
         Io_Ports.Write_Io_Port(Pctl1_Addr, Output_Init2);
         Io_Ports.Write_Io_Port(Qctl1_Addr, Output_Init2);
         Io_Ports.Write_Io_Port(Pctl2_Addr, Output_Init2);
         Io_Ports.Write_Io_Port(Qctl2_Addr, Output_Init2);
         -- init 24-bits mixed input & output
         Io_Ports.Write_Io_Port(Pctl3_Addr, Pctl3_Init2);
         Io_Ports.Write_Io_Port(Qctl3_Addr, Qctl3_Init2);


      end Init_Blocks;

   end Object;


   --PUBLIC PROCEDURES

   --Set block Cab
   procedure Set_Cab (
         B   : in     Raildefs.Block_Id;
         Cab : in     Raildefs.Cab_Type) is
   begin
      Object.Set_Cab (B,Cab);
   end Set_Cab;

   --Set block polarity
   procedure Set_Polarity (
         B   : in     Raildefs.Block_Id;
         Pol : in     Raildefs.Polarity_Type) is
   begin
      Object.Set_Polarity (B,Pol);
   end Set_Polarity;

   --Flip block polarity
   procedure Flip_Block (
         B : in     Raildefs.Block_Id) is
   begin
      Object.Flip_Block (B);
   end Flip_Block;

   --Init Blocks
   procedure Init_Blocks is
      use Dio192defs;
      Temp : Unsigned_8;
   begin
      Object.Init_Blocks;
   end Init_Blocks;


end Dio192_Blocks;